#include "systime.h"
#include "led.h"
#include <stdio.h>

#define DEEP_SLEEP_ARR (40) // 20ms    N = n_ms*32800/1000/16 - 1
#define RUN_MODE_ARR 1      // 0.8333*6=5ms

#define DEPP_SLEEP_PERIOD 20 // 唤醒周期
#define RUN_MODE_PERIOD 1

static timestamp_t sys_time;

static void ctrim_init(void);
static void systime_update(void);

// 系统默认时钟PCLK = HCLK = systemclk = RCHCLKD =4MHZ
static void ctrim_init(void)
{
    stc_ctrim_timer_init_t stcCfg = {0};

    /* 第一步：开启CTRIM 外设时钟 */
    SYSCTRL_PeriphClkEnable(SYSCTRL_PERIRESET_CTRIM);

    /* 第二步：复位CTRIM模块 */
    SYSCTRL_PeriphReset(SYSCTRL_PERIRESET_CTRIM);

    /* 第三步：TRIM 初始化配置 */
    stcCfg.u32Clock = CTRIM_ACCURATE_CLOCK_RCL;
    stcCfg.u32ClockDiv = CTRIM_REF_CLOCK_DIV16;
    stcCfg.u32EtrFilter = CTRIM_ETR_CLOCK_FILTER_NONE;
    stcCfg.u32ReloadVal = DEEP_SLEEP_ARR; ///< 定时约20ms，32800/1000/16 * 20 - 1 = 41 - 1 = 40
    CTRIM_TimerInit(CTRIM, &stcCfg);

    /* 第四步：清除所有标志位 */
    CTRIM_ClearFlag_ALL(CTRIM);
    /* 第五步：使能中断 */
    CTRIM_EnableIT(CTRIM, CTRIM_IT_UD);      ///< 计数器下溢中断 使能
    EnableNvic(CTRIM_IRQn, IrqLevel3, TRUE); ///< 使能并配置TRIM 系统中断

    CTRIM_Enable(CTRIM); ///< 使能CTRIM模块
}

void systime_init(void)
{
    ctrim_init();

    sys_time.sec = 0;
    sys_time.msec = 0;
}

void Ctrim_IRQHandler(void)
{
    if (TRUE == CTRIM_IsActiveFlag(CTRIM, CTRIM_FLAG_UD))
    {
        CTRIM_ClearFlag(CTRIM, CTRIM_CLEAR_FLAG_UD); ///< 清除标志位
        systime_update();
    }
}

void systime_enter_sleep(void)
{
    LPM_GotoDeepSleep(FALSE);
}
static void systime_update(void)
{
    sys_time.msec += DEPP_SLEEP_PERIOD;
    if (sys_time.msec >= 1000)
    {
        sys_time.sec += sys_time.msec / 1000;
        sys_time.msec %= 1000;
    }
}

void get_current_systime(timestamp_t *time)
{
    time->sec = sys_time.sec;
    time->msec = sys_time.msec;
}
// 该函数是再系统时间的基础上加上相对时间，而不是传入的时间，传入时间会被覆盖
void relative_time_add_ms(timestamp_t *time, uint16_t ms)
{
    uint16_t temp = sys_time.msec + ms;

    time->sec = sys_time.sec + (temp / 1000);
    time->msec = temp % 1000;
}

void relative_time_add_sec(timestamp_t *time, uint32_t s)
{
    time->sec = sys_time.sec + s;
    time->msec = sys_time.msec;
}

uint8 is_relative_time_timeout(const timestamp_t *time)
{
    if (sys_time.sec > time->sec)
        return TRUE;
    if ((sys_time.sec == time->sec) && (sys_time.msec >= time->msec))
        return TRUE;

    return FALSE;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief  阻塞延时，慎用，单位s
/// @param  阻塞延时时间
/// @retval
////////////////////////////////////////////////////////////////////////////////
void relative_time_delay_sec(uint32_t s)
{
    timestamp_t time;
    relative_time_add_sec(&time, s);
    while (!is_relative_time_timeout(&time))
        systime_enter_sleep();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief  阻塞延时，慎用，单位ms
/// @param  阻塞延时时间 ,最大值 65535
/// @retval
////////////////////////////////////////////////////////////////////////////////
void relative_time_delay_msec(uint16_t ms)
{
    timestamp_t time;
    relative_time_add_ms(&time, ms);
    while (!is_relative_time_timeout(&time))
        systime_enter_sleep();
}
